﻿namespace DomainServices.Tools.Pdb.SymStore
{
    using System;
    using System.Diagnostics.SymbolStore;
    using System.Runtime.InteropServices;
    using System.Text;

    internal class SymMethod : ISymbolEnCMethod, ISymbolMethod
    {
        private ISymUnmanagedMethod m_unmanagedMethod;

        public SymMethod(ISymUnmanagedMethod unmanagedMethod)
        {
            if (unmanagedMethod == null)
            {
                throw new ArgumentNullException("unmanagedMethod");
            }
            this.m_unmanagedMethod = unmanagedMethod;
        }

        public string GetFileNameFromOffset(int dwOffset)
        {
            int pcchName = 0;
            ((ISymENCUnmanagedMethod) this.m_unmanagedMethod).GetFileNameFromOffset(dwOffset, 0, out pcchName, null);
            StringBuilder name = new StringBuilder(pcchName);
            ((ISymENCUnmanagedMethod) this.m_unmanagedMethod).GetFileNameFromOffset(dwOffset, pcchName, out pcchName, name);
            return name.ToString();
        }

        public int GetLineFromOffset(int dwOffset, out int pcolumn, out int pendLine, out int pendColumn, out int pdwStartOffset)
        {
            int pline = 0;
            ((ISymENCUnmanagedMethod) this.m_unmanagedMethod).GetLineFromOffset(dwOffset, out pline, out pcolumn, out pendLine, out pendColumn, out pdwStartOffset);
            return pline;
        }

        public ISymbolNamespace GetNamespace()
        {
            ISymUnmanagedNamespace retVal = null;
            this.m_unmanagedMethod.GetNamespace(out retVal);
            return new SymNamespace(retVal);
        }

        public int GetOffset(ISymbolDocument document, int line, int column)
        {
            int retVal = 0;
            this.m_unmanagedMethod.GetOffset(((SymbolDocument) document).InternalDocument, line, column, out retVal);
            return retVal;
        }

        public ISymbolVariable[] GetParameters()
        {
            int pcParams = 0;
            this.m_unmanagedMethod.GetParameters(0, out pcParams, null);
            ISymUnmanagedVariable[] parms = new ISymUnmanagedVariable[pcParams];
            this.m_unmanagedMethod.GetParameters(pcParams, out pcParams, parms);
            ISymbolVariable[] variableArray2 = new ISymbolVariable[pcParams];
            for (uint i = 0; i < pcParams; i++)
            {
                variableArray2[i] = new SymVariable(parms[i]);
            }
            return variableArray2;
        }

        public int[] GetRanges(ISymbolDocument document, int line, int column)
        {
            int pcRanges = 0;
            this.m_unmanagedMethod.GetRanges(((SymbolDocument) document).InternalDocument, line, column, 0, out pcRanges, null);
            int[] ranges = new int[pcRanges];
            this.m_unmanagedMethod.GetRanges(((SymbolDocument) document).InternalDocument, line, column, pcRanges, out pcRanges, ranges);
            return ranges;
        }

        public ISymbolScope GetScope(int offset)
        {
            ISymUnmanagedScope retVal = null;
            this.m_unmanagedMethod.GetScopeFromOffset(offset, out retVal);
            return new SymScope(retVal);
        }

        public void GetSequencePoints(int[] offsets, ISymbolDocument[] documents, int[] lines, int[] columns, int[] endLines, int[] endColumns)
        {
            int length = 0;
            if (offsets != null)
            {
                length = offsets.Length;
            }
            else if (documents != null)
            {
                length = documents.Length;
            }
            else if (lines != null)
            {
                length = lines.Length;
            }
            else if (columns != null)
            {
                length = columns.Length;
            }
            else if (endLines != null)
            {
                length = endLines.Length;
            }
            else if (endColumns != null)
            {
                length = endColumns.Length;
            }
            if (length != 0)
            {
                if ((offsets != null) && (length != offsets.Length))
                {
                    throw new ArgumentException();
                }
                if ((lines != null) && (length != lines.Length))
                {
                    throw new ArgumentException();
                }
                if ((columns != null) && (length != columns.Length))
                {
                    throw new ArgumentException();
                }
                if ((endLines != null) && (length != endLines.Length))
                {
                    throw new ArgumentException();
                }
                if ((endColumns != null) && (length != endColumns.Length))
                {
                    throw new ArgumentException();
                }
                ISymUnmanagedDocument[] documentArray = new ISymUnmanagedDocument[documents.Length];
                int pcPoints = 0;
                this.m_unmanagedMethod.GetSequencePoints(documents.Length, out pcPoints, offsets, documentArray, lines, columns, endLines, endColumns);
                for (uint i = 0; i < documents.Length; i++)
                {
                    documents[i] = new SymbolDocument(documentArray[i]);
                }
            }
        }

        public bool GetSourceStartEnd(ISymbolDocument[] docs, int[] lines, int[] columns)
        {
            bool retVal = false;
            int length = 0;
            if (docs != null)
            {
                length = docs.Length;
            }
            else if (lines != null)
            {
                length = lines.Length;
            }
            else if (columns != null)
            {
                length = columns.Length;
            }
            if (length < 2)
            {
                throw new ArgumentException();
            }
            if ((docs != null) && (length != docs.Length))
            {
                throw new ArgumentException();
            }
            if ((lines != null) && (length != lines.Length))
            {
                throw new ArgumentException();
            }
            if ((columns != null) && (length != columns.Length))
            {
                throw new ArgumentException();
            }
            ISymUnmanagedDocument[] documentArray = new ISymUnmanagedDocument[docs.Length];
            this.m_unmanagedMethod.GetSourceStartEnd(documentArray, lines, columns, out retVal);
            if (retVal)
            {
                for (uint i = 0; i < docs.Length; i++)
                {
                    docs[i] = new SymbolDocument(documentArray[i]);
                }
            }
            return retVal;
        }

        public ISymUnmanagedMethod InternalMethod
        {
            get
            {
                return this.m_unmanagedMethod;
            }
        }

        public ISymbolScope RootScope
        {
            get
            {
                ISymUnmanagedScope retVal = null;
                this.m_unmanagedMethod.GetRootScope(out retVal);
                return new SymScope(retVal);
            }
        }

        public int SequencePointCount
        {
            get
            {
                int retVal = 0;
                this.m_unmanagedMethod.GetSequencePointCount(out retVal);
                return retVal;
            }
        }

        public SymbolToken Token
        {
            get
            {
                SymbolToken token;
                this.m_unmanagedMethod.GetToken(out token);
                return token;
            }
        }
    }
}

